package com.butterfly.hotkey.client.core.netty;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.butterfly.hotkey.client.core.config.AppClientProperties;
import com.butterfly.hotkey.client.core.service.NettyService;
import com.butterfly.hotkey.core.constant.Constants;
import com.butterfly.hotkey.core.model.HotKeyModel;
import com.butterfly.hotkey.core.model.msg.HotKeyMsg;
import com.butterfly.hotkey.core.util.FastJsonUtil;
import com.butterfly.hotkey.core.util.NettyMsgUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.butterfly.hotkey.core.constant.MsgTypeConst.*;

/**
 * @author butterfly
 * @version 1.0
 */
@ChannelHandler.Sharable
public class AppNettyClientHandler extends SimpleChannelInboundHandler<String> {

    private static final Logger log = LoggerFactory.getLogger(Constants.CLIENT);

    private final AppClientProperties clientProperties;
    private final NettyService nettyService;

    public AppNettyClientHandler(AppClientProperties clientProperties, NettyService nettyService) {
        this.nettyService = nettyService;
        this.clientProperties = clientProperties;
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            if (idleStateEvent.state() == IdleState.ALL_IDLE) {
                //向服务端发送心跳
                String appName = clientProperties.getAppName();
                ctx.writeAndFlush(NettyMsgUtil.buildByteBuf(new HotKeyMsg(PING, appName)));
            }
        }
        super.userEventTriggered(ctx, evt);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // worker不再有效
        nettyService.handleWorkerInactive(ctx);

        super.channelInactive(ctx);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("client channel in active:{}", ctx.name());
        super.channelActive(ctx);

        // 发送客户端连接消息，并推送rule
        String appName = clientProperties.getAppName();
        HotKeyMsg hotKeyMsg = new HotKeyMsg(APP_CONNECT, appName);
        hotKeyMsg.setClientKeyRules(clientProperties.getClientKeyRules());
        ctx.writeAndFlush(NettyMsgUtil.buildByteBuf(hotKeyMsg));
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext,
                                String nettyMsg) {
        HotKeyMsg msg = FastJsonUtil.parseObject(nettyMsg, HotKeyMsg.class);

        if (PONG == msg.getMsgType()) {
            log.info("heart beat");
            return;
        }
        if (RESPONSE_NEW_HOT_KEY == msg.getMsgType()) {
            log.info("receive new key: {}", JSON.toJSONString(msg));
            if (CollectionUtil.isEmpty(msg.getHotKeyModels())) {
                return;
            }
            for (HotKeyModel model : msg.getHotKeyModels()) {
                // 接收新的hotkey，异步标记hotkey
                nettyService.handleNewKey(model);

            }
        }
    }
}
